package atom.core0.object;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

public class ClassUtil
{
	protected final static Logger logger = Logger.getLogger(ClassUtil.class);

	public static boolean compareParameterTypes(Class[] parameterTypes, Class[] orgParameterTypes)
	{
		// parameterTypes 里面，int->Integer
		// orgParameterTypes是原始参数类型
		if (parameterTypes == null && orgParameterTypes == null)
			return true;
		if (parameterTypes == null && orgParameterTypes != null)
		{
			if (orgParameterTypes.length == 0)
				return true;
			else
				return false;
		}
		if (parameterTypes != null && orgParameterTypes == null)
		{
			if (parameterTypes.length == 0)
				return true;
			else
				return false;
		}
		if (parameterTypes.length != orgParameterTypes.length)
			return false;
		/*
		 * for(int i=0;i<parameterTypes.length;i++) { //序列化时，byte 没转成Byte
		 * char也不需要Character //由于HashMap Map都可能是参数，所以会导致无法比较参数，只能比较个数就行了 if
		 * (orgParameterTypes[i]==short.class) orgParameterTypes[i]=Short.class;
		 * else if (orgParameterTypes[i]==int.class)
		 * orgParameterTypes[i]=Integer.class; else if
		 * (orgParameterTypes[i]==long.class) orgParameterTypes[i]=Long.class;
		 * else if (orgParameterTypes[i]==double.class)
		 * orgParameterTypes[i]=Double.class; else if
		 * (orgParameterTypes[i]==float.class) orgParameterTypes[i]=Float.class;
		 * else if (orgParameterTypes[i]==boolean.class)
		 * orgParameterTypes[i]=Boolean.class; //else if
		 * (orgParameterTypes[i]==byte.class) //
		 * orgParameterTypes[i]=Byte.class; //else if
		 * (orgParameterTypes[i]==char.class) //
		 * orgParameterTypes[i]=Character.class;
		 * 
		 * if (parameterTypes[i]!=orgParameterTypes[i]) return false;
		 * 
		 * }
		 */
		return true;
	}

	// int Integer long Long double Double
	public static Method getMethod(Method[] methods, String methodName, Class[] parameterTypes)
	{
		for (int i = 0; i < methods.length; i++)
		{
			if (!methods[i].getName().equals(methodName))
				continue;
			if (compareParameterTypes(parameterTypes, methods[i].getParameterTypes()))
				return methods[i];
		}
		return null;
	}
	public static Method getGetMethod(Class myClass, String fieldName)
	{
		try
		{
			String firstLetter = fieldName.substring(0, 1).toUpperCase();
			String getMethodName = "get" + firstLetter + fieldName.substring(1);
			
			return myClass.getDeclaredMethod(getMethodName, new Class[]{});
		}
		catch(Exception e)
		{
			logger.warn("找不到类:"+myClass.getName()+"对应的set方法:"+fieldName);
			return null;
		}
	}
	public static Method getSetMethod(Class myClass, String fieldName, Class[] parameterTypes)
	{
		try
		{
			String firstLetter = fieldName.substring(0, 1).toUpperCase();
			String setMethodName = "set" + firstLetter + fieldName.substring(1);
			
			return myClass.getDeclaredMethod(setMethodName, parameterTypes);
		}
		catch(Exception e)
		{
			logger.warn("找不到类:"+myClass.getName()+"对应的set方法:"+fieldName);
			return null;
		}
	}

	public static Object getMethod(Object object, String fieldName) throws Exception
	{
		Class classType = object.getClass();
		String firstLetter = fieldName.substring(0, 1).toUpperCase();
		String getMethodName = "get" + firstLetter + fieldName.substring(1);
		String setMethodName = "set" + firstLetter + fieldName.substring(1);
		// 获得对应的getXxxx方法....
		Method getMethod = classType.getMethod(getMethodName, new Class[] {});

		Object value = getMethod.invoke(object, new Object[] {});
		return value;
	}

	public static void setMethod(Object object, String fieldName, Object value) throws Exception
	{
		Class classType = object.getClass();
		Field field = getField(object, fieldName);
		String firstLetter = fieldName.substring(0, 1).toUpperCase();
		String setMethodName = "set" + firstLetter + fieldName.substring(1);
		// 获得对应的setXxxx方法.....
		Method setMethod = classType.getMethod(setMethodName, new Class[] { field.getType() });
		setMethod.invoke(object, new Object[] { value });

	}

	public static Object invokeGetMethod(Object object, String fieldName) throws Exception
	{
		Class classType = object.getClass();
		String firstLetter = fieldName.substring(0, 1).toUpperCase();
		String getMethodName = "get" + firstLetter + fieldName.substring(1);
		String setMethodName = "set" + firstLetter + fieldName.substring(1);
		// 获得对应的getXxxx方法....
		Method getMethod = classType.getMethod(getMethodName, new Class[] {});

		Object value = getMethod.invoke(object, new Object[] {});
		return value;
	}

	public static void invokeSetMethod(Object object, String fieldName, Object value) throws Exception
	{
		Class classType = object.getClass();
		Field field = getField(object, fieldName);
		String firstLetter = fieldName.substring(0, 1).toUpperCase();
		String setMethodName = "set" + firstLetter + fieldName.substring(1);
		// 获得对应的setXxxx方法.....
		Method setMethod = classType.getMethod(setMethodName, new Class[] { field.getType() });
		setMethod.invoke(object, new Object[] { value });

	}

	private static Field getField(Object object, String fieldName)
	{
		Class classType = object.getClass();
		Field fields[] = classType.getDeclaredFields();
		for (int i = 0; i < fields.length; i++)
		{
			Field field = fields[i];
			if (field.getName().equals(fieldName))
				return field;
		}
		return null;
	}

	// 0是调用函数
	public static StackTraceElement getCallerClass(int deep)
	{
		StackTraceElement stack[] = (new Throwable()).getStackTrace();
		for (int i = 0; i < stack.length; i++)
		{
			StackTraceElement s = stack[i];
			return s;
		}
		return null;
	}

	public static String getCallerClassInfo(int deep)
	{
		String info = "";
		StackTraceElement stack[] = (new Throwable()).getStackTrace();
		if (deep >= stack.length)
			return "";
		StackTraceElement s = stack[deep];
		info += s.getClassName();
		return info;
	}

	public static String getCallerMethodInfo(int deep)
	{
		String info = "";
		StackTraceElement stack[] = (new Throwable()).getStackTrace();
		if (deep >= stack.length)
			return "";
		StackTraceElement s = stack[deep];
		info += s.getClassName() + "." + s.getMethodName() + "(" + s.getFileName() + ":" + s.getLineNumber() + ")";
		return info;
	}

	public static void printStack()
	{
		StackTraceElement stack[] = (new Throwable()).getStackTrace();
		for (int i = 0; i < stack.length; i++)
		{
			StackTraceElement s = stack[i];
			System.out.format(" ClassName:%d\t%s\n", i, s.getClassName());
			System.out.format("MethodName:%d\t%s\n", i, s.getMethodName());
			System.out.format("  FileName:%d\t%s\n", i, s.getFileName());
			System.out.format("LineNumber:%d\t%s\n\n", i, s.getLineNumber());
		}
	}

	public static void printStack(Throwable t)
	{
		StackTraceElement stack[] = t.getStackTrace();
		for (int i = 0; i < stack.length; i++)
		{
			StackTraceElement s = stack[i];
			System.out.println("    at " + s);
		}
	}

	public static void printCauseStack(Throwable t)
	{
		System.out.println("Caused by:" + t.getMessage());
		printStack(t.getCause());
	}

	private static String getStackString(Throwable t)
	{
		if (t == null)
			return "";
		StringBuffer sb = new StringBuffer();
		StackTraceElement stack[] = t.getStackTrace();
		for (int i = 0; i < stack.length; i++)
		{
			StackTraceElement s = stack[i];
			sb.append("    at " + s + "\n");
		}
		return sb.toString();
	}

	public static String getThrowableStackString(Throwable t)
	{
		String head = t.getClass().getName() + ": " + t.getMessage() + "\n";
		String body = getStackString(t);
		return head + body;
	}

	public static String getCauseStackString(Throwable t)
	{
		String head = "Caused by:" + t.getMessage() + "\n";
		String body = getStackString(t.getCause());
		return head + body;
	}

	public static String getThrowableStackInfo(Throwable t)
	{
		String head = getThrowableStackString(t);
		String body = getCauseStackString(t);
		return head + body;
	}

	public static Class[] getArgTypes(Object[] args)
	{
		if (args == null)
			return null;
		if (args.length == 0)
			return null;
		Class[] myclass = new Class[args.length];
		for (int i = 0; i < args.length; i++)
		{
			if (args[i] != null)
				myclass[i] = args[i].getClass();
		}
		return myclass;
	}

	public static List<String> getMethodNameList(Class classType, String prefix)
	{
		// Field fields[] = classType.getDeclaredFields();
		// classType.getMethods();
		Method fields[] = classType.getDeclaredMethods();
		ArrayList<String> list = new ArrayList();
		if (fields.length > 0)
		{
			for (int i = 0; i < fields.length; i++)
			{
				Method field = fields[i];
				if (field.getName().startsWith(prefix))
				{
					String firstLetter = field.getName().substring(3, 4).toLowerCase();
					String info = field.getName().substring(4);
					list.add(firstLetter + info);
				}
			}
		}

		return list;
	}

	public static Map<String, Method> getMethodMap(Class classType, String prefix)
	{
		Method methods[] = classType.getDeclaredMethods();
		Map<String, Method> map = new HashMap();
		if (methods.length > 0)
		{
			for (int i = 0; i < methods.length; i++)
			{
				Method method = methods[i];
				if (method.getName().startsWith(prefix))
				{
					String firstLetter = method.getName().substring(3, 4).toLowerCase();
					String info = method.getName().substring(4);
					map.put(firstLetter + info, method);
				}
			}
		}

		return map;
	}
	 public static boolean isJavaClass(Class<?> clz) {  
		    return clz != null && clz.getClassLoader() == null;  
		  }  
	// public static String getTableName(Class myClass) //MyORMBaseBean bean
	// {
	// Table annotations = (Table)myClass.getAnnotation(Table.class);
	// String tableName;
	// tableName = annotations.name();
	// return tableName;
	// }
	// public static Map<String,String> getMethodFieldMap(Map<String,Method>
	// methodMap)
	// {
	// LinkedHashMap myMap = new LinkedHashMap();
	// Iterator it=methodMap.entrySet().iterator();
	// while(it.hasNext()){
	// Map.Entry entry=(Map.Entry)it.next();
	// String beanField = (String)entry.getKey();
	// Method method = (Method)entry.getValue();
	// boolean hasAnnotation=method.isAnnotationPresent(Column.class) ;
	// if (!hasAnnotation)
	// continue;
	// Column column = method.getAnnotation(Column.class);
	// String dbField = column.name();
	// myMap.put(beanField, dbField);
	// }
	// return myMap;
	//		
	// }
	
}
